package fx.mine.active.component.music;

import animatefx.animation.FadeOut;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.dtflys.forest.Forest;
import fx.mine.active.component.music.api.MusicApi;
import fx.mine.active.util.CacheUtil;
import io.github.palexdev.materialfx.controls.MFXListView;
import io.github.palexdev.materialfx.controls.cell.MFXListCell;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.geometry.Pos;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import lombok.Data;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Log4j2
public class MusicPane extends AnchorPane {
    private static final float PIC_W = 250f;
    private static final float PIC_H = 250f;
    private static final int PRE_LEFT = 30;
    private static final int GAP = 310;
    @Getter
    private final PlayItemsContent playItems = new PlayItemsContent();
    @Getter
    private final LyricsContainer lyricsContainer = new LyricsContainer();

    @Getter
    private final PlayerContainer playerContainer = new PlayerContainer();

    public MusicPane(double width, double height) {
        setPrefSize(width, height);
        var slider = new SliderContainer();
        getChildren().add(slider);

        getChildren().add(lyricsContainer);

        getChildren().add(playItems);

        var navPane = new PlayListNavPane();
        getChildren().add(navPane);

        getChildren().add(playerContainer);

        getStyleClass().add("musicPane");
        getStylesheets().add(getClass().getResource("/css/musicPane.css").toExternalForm());
    }

    @Log4j2
    static class LyricsContainer extends AnchorPane {
        private final MFXListView<String> mfxListView;

        public LyricsContainer() {
            AnchorPane.setTopAnchor(this, 300.0);
            AnchorPane.setLeftAnchor(this, 50.0);
            AnchorPane.setRightAnchor(this, 50.0);
            AnchorPane.setBottomAnchor(this, 45.0);

            this.mfxListView = new MFXListView<>();
            mfxListView.setCellFactory(new Function<String, MFXListCell<String>>() {
                @Override
                public MFXListCell<String> apply(String s) {
                    MFXListCell<String> cell = new MFXListCell<>(mfxListView, s);
                    cell.updateItem(s);
                    cell.setAlignment(Pos.CENTER);
                    return cell;
                }
            });

            AnchorPane.setLeftAnchor(mfxListView, 0.0);
            AnchorPane.setTopAnchor(mfxListView, 0.0);
            AnchorPane.setBottomAnchor(mfxListView, 0.0);
            AnchorPane.setRightAnchor(mfxListView, 0.0);
            getChildren().add(mfxListView);

            getStyleClass().add("lyrics");
        }

        public void paddingContent(long songId) {
            MusicApi client = Forest.client(MusicApi.class);
            String lyricStr = client.lyric(songId);
            JSONObject jsonObject = JSON.parseObject(lyricStr);
            String lyric = (String) JSONPath.eval(jsonObject, "$.lrc.lyric");
            mfxListView.getItems().clear();
            mfxListView.setItems(FXCollections.observableArrayList(lyric.split("\n")));
        }
    }

    /**
     * 这里是歌单显示区域
     */
    @SuppressWarnings("all")
    class PlayListNavPane extends AnchorPane {
        public PlayListNavPane() {
            AnchorPane.setTopAnchor(this, 300.0);
            AnchorPane.setLeftAnchor(this, 50.0);
            AnchorPane.setRightAnchor(this, 50.0);
            AnchorPane.setBottomAnchor(this, 45.0);

            String hotUrl = CacheUtil.getByCache("music.hotStr");
            JSONObject rootObject = JSON.parseObject(hotUrl);

            List<Recommend> playItemList = null;
            try {
                playItemList = (List<Recommend>) ((JSONArray) rootObject.get("recommend")).stream()
                        .map(o -> {
                            JSONObject object = (JSONObject) o;
                            log.info("parsing {}", object);
                            var recommend = new Recommend();
                            recommend.setId(object.getLong("id"));
                            recommend.setName((String) JSONPath.eval(o, "$.name"));
                            recommend.setPicUrl((String) JSONPath.eval(o, "$.picUrl"));
                            return recommend;
                        }).collect(Collectors.toList());
            } catch (Exception e) {
                log.error("音乐导航不可用", e);
            }

            List<List<Recommend>> lists = ListUtil.partition(playItemList, 3);
            if (CollectionUtil.isNotEmpty(lists)) {
                List<Recommend> list = lists.get(0);
                if (CollectionUtil.isNotEmpty(list)) {
                    for (int i = 0; i < list.size(); i++) {
                        Recommend recommend = list.get(i);
                        PlayListItemPane itemPane = new PlayListItemPane(recommend.getPicUrl(), recommend.getName(), PIC_W, PIC_H);
                        itemPane.setUserData(recommend);
                        itemPane.anchor(PRE_LEFT + GAP * i, 0, PRE_LEFT, 0);
                        itemPane.setOnMouseClicked(event -> {
                            Recommend userData = (Recommend) ((PlayListItemPane) event.getSource()).getUserData();
                            long id = userData.getId();
                            Platform.runLater(() -> {
                                showPlayList(id);
                                switchPreviwIcon(userData.getPicUrl());
                            });
                        });
                        getChildren().add(itemPane);
                    }
                }
            }
            getStyleClass().add("navPane");
        }

        public void switchPreviwIcon(String picUrl) {
            playerContainer.getDynPreviewIconUrl().set(picUrl);
        }

        private void showPlayList(long id) {
            MusicApi client = Forest.client(MusicApi.class);
            String jsonStr = client.playListTrackAll(id, 0);
            log.info("playList = {}", jsonStr);

            playItems.trigger(jsonStr);

            FadeOut fadeOut = new FadeOut();
            fadeOut.setNode(PlayListNavPane.this);
            fadeOut.setOnFinished(e -> {
                playItems.toFront();
                playerContainer.toFront();
            });
            fadeOut.play();
        }

        @Data
        static class Recommend {
            private long id;
            private String type;
            private String name;
            private String picUrl;
            private String alg;
        }

        @Log4j2
        static class PlayListItemPane extends VBox {
            public PlayListItemPane(String url, String txt, double width, double height) {
                ImageView imageView = new ImageView(url);
                imageView.setFitWidth(width);
                imageView.setFitHeight(height);
                getChildren().add(imageView);
                setAlignment(Pos.CENTER);
                setSpacing(10d);

                Text text = new Text(txt);
                getChildren().add(text);
            }

            public void anchor(double left, double right, double top, double bottom) {
                if (left > 0.0) {
                    AnchorPane.setLeftAnchor(this, left);
                }
                if (right > 0.0) {
                    AnchorPane.setRightAnchor(this, right);
                }
                if (top > 0.0) {
                    AnchorPane.setTopAnchor(this, top);
                }
                if (bottom > 0.0) {
                    AnchorPane.setBottomAnchor(this, bottom);
                }
            }
        }
    }
}
